#!/usr/bin/env python3

#  Copyright © 2015 SpaghettiToastBook
#
#  This file is part of Dimension BX2.1.
#
#  Dimension BX2.1 is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  Dimension BX2.1 is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with Dimension BX2.1. If not, see <http://www.gnu.org/licenses/>.

from functools import partial
import pyglet
from pyglet.window import key, mouse
from gamewide import *

"""Module containing the Controls class for handling key/mouse controls."""

__all__ = ['controls']

class Controls(pyglet.event.EventDispatcher):

    def __init__(self):
        self.controls_up = [key.UP, key.W]
        self.controls_down = [key.DOWN, key.S]
        self.controls_left = [key.LEFT, key.A]
        self.controls_right = [key.RIGHT, key.D]
        self.controls_restart = [key.R]
        self.controls_pause = [key.P]

        self.firing_rate = 1 / 4

        self.up = set()
        self.down = set()
        self.left = set()
        self.right = set()
        self.firing = False
        self.mouse_x = 0
        self.mouse_y = 0

        window.push_handlers(self)

    def _dispatch_fire_event(self, dt=None):
        self.dispatch_event('on_fire', self.mouse_x, self.mouse_y)

    def on_key_press(self, key, modifiers):
        if key in self.controls_up:
            self.up.add(key)
            if len(self.up) == 1:
                self.dispatch_event('on_up_press')
        elif key in self.controls_down:
            self.down.add(key)
            if len(self.down) == 1:
                self.dispatch_event('on_down_press')
        elif key in self.controls_right:
            self.right.add(key)
            if len(self.right) == 1:
                self.dispatch_event('on_right_press')
        elif key in self.controls_left:
            self.left.add(key)
            if len(self.left) == 1:
                self.dispatch_event('on_left_press')
        elif key in self.controls_restart:
            self.dispatch_event('on_restart_press')
        elif key in self.controls_pause:
            self.dispatch_event('on_pause_press')

    def on_key_release(self, key, modifiers):
        if key in self.controls_up:
            self.up.remove(key)
            if len(self.up) == 0:
                self.dispatch_event('on_up_release')
        elif key in self.controls_down:
            self.down.remove(key)
            if len(self.down) == 0:
                self.dispatch_event('on_down_release')
        elif key in self.controls_right:
            self.right.remove(key)
            if len(self.right) == 0:
                self.dispatch_event('on_right_release')
        elif key in self.controls_left:
            self.left.remove(key)
            if len(self.left) == 0:
                self.dispatch_event('on_left_release')

    def on_mouse_motion(self, x, y, dx, dy):
        self.mouse_x = x
        self.mouse_y = y

    def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers):
        self.mouse_x = x
        self.mouse_y = y

    def on_mouse_press(self, x, y, buttons, modifiers):
        if buttons & mouse.LEFT and not self.firing:
            self.firing = True
            self._dispatch_fire_event()
            pyglet.clock.schedule_interval(self._dispatch_fire_event,
                                           self.firing_rate)

    def on_mouse_release(self, x, y, buttons, modifiers):
        if buttons & mouse.LEFT and self.firing:
            self.firing = False
            pyglet.clock.unschedule(self._dispatch_fire_event)

for direction in ('up', 'down', 'right', 'left'):
    for state in ('press', 'release'):
        Controls.register_event_type('on_{}_{}'.format(direction, state))
Controls.register_event_type('on_fire')
Controls.register_event_type('on_restart_press')
Controls.register_event_type('on_pause_press')

controls = Controls()
